/*
 * Powered By XY
 * Since 2020
 */
package com.xy.biz.fd.service.impl;

import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

import com.xy.biz.base.client.DictClient;
import com.xy.biz.base.domain.req.GetDictByCodeRequest;
import com.xy.biz.base.domain.resp.ListDictItemResponse;
import com.xy.biz.fd.domain.DocumentPermissions;
import com.xy.biz.fd.domain.bo.DocumentBO;
import com.xy.biz.fd.domain.bo.FolderBO;
import com.xy.biz.fd.domain.consts.RepositoryConstant;
import com.xy.biz.fd.domain.converter.DocumentConverter;
import com.xy.biz.fd.domain.converter.FolderConverter;
import com.xy.biz.fd.domain.converter.RepositoryConverter;
import com.xy.biz.fd.domain.query.DocumentQuery;
import com.xy.biz.fd.domain.query.FolderQuery;
import com.xy.biz.fd.domain.req.repository.GetTypeRepositoryRequest;
import com.xy.biz.fd.domain.resp.GetDocumentResponse;
import com.xy.biz.fd.domain.resp.GetFolderResponse;
import com.xy.biz.fd.domain.resp.GetRepositoryResponse;
import com.xy.biz.fd.domain.vo.TeamRepositoryTreeItem;
import com.xy.biz.fd.manager.DocumentManager;
import com.xy.biz.fd.manager.DocumentRubbishManager;
import com.xy.biz.fd.manager.FolderManager;
import com.xy.biz.fd.service.DocumentService;
import com.xy.biz.fd.service.FolderService;
import com.xy.biz.fd.strategy.RepositoryFilterStrategy;
import com.xy.biz.uc.client.TeamClient;
import com.xy.biz.uc.client.TeamEventBusClient;
import com.xy.biz.uc.client.UserClient;
import com.xy.biz.uc.client.UserGroupClient;
import com.xy.biz.uc.domain.dto.UserDTO;
import com.xy.biz.uc.domain.req.*;
import com.xy.biz.uc.domain.resp.GetTeamResponse;
import com.xy.biz.uc.domain.resp.GetUserGroupResponse;
import com.xy.lang.domain.LongIdCodeName;
import com.xy.lang.domain.Result;
import com.xy.lang.util.CalendarUtils;
import com.xy.lang.util.ResultUtils;
import com.xy.tool.context.UserContextHolder;
import com.xy.tool.util.ConvertSizeUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.xy.biz.fd.domain.bo.RepositoryBO;
import com.xy.biz.fd.domain.query.RepositoryQuery;
import com.xy.biz.fd.service.RepositoryService;
import com.xy.biz.fd.manager.RepositoryManager;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import static com.xy.biz.fd.strategy.RepositoryFilterStrategy.REPOSITORY_FILTER;
import static java.util.stream.Collectors.toList;

/**
 *
 * @author ssl
 * @date 2021-1-18
 */
@Slf4j
@Service
public class RepositoryServiceImpl implements RepositoryService, InitializingBean {

    @Autowired
    private RepositoryManager repositoryManager;
    @Autowired
    private FolderManager folderManager;
    @Autowired
    private DocumentEventBus documentEventBus;
    @Autowired
    private DocumentManager documentManager;
    @Autowired
    private DocumentService documentService;
    @Autowired
    private FolderService folderService;
    @Autowired
    private DocumentRubbishManager documentRubbishManager;
    @Autowired
    private UserClient userClient;
    @Autowired
    private UserGroupClient userGroupClient;
    @Autowired
    private TeamClient teamClient;
    @Autowired
    private DictClient dictClient;
    @Autowired
    private Map<String, RepositoryFilterStrategy> generatorMap;
    @Autowired
    private TeamEventBusClient teamEventBusClient;
    @Autowired
    private RepositoryEventBus repositoryEventBus;

    static enum RepositoryEnum {
        OWN_REPOSITORY(-1L, "个人知识库");

        private long code;
        private String name;

        RepositoryEnum(long code, String name) {
            this.code = code;
            this.name = name;
        }

        public long getCode() {
            return code;
        }

        public String getName() {
            return name;
        }
    }

    @Override
    public Result<?> saveRepository(RepositoryBO repositoryBO) {
        return saveRepositoryService(repositoryBO);
    }

    private Result<? extends Long> saveRepositoryService(RepositoryBO repositoryBO) {
        //获取知识库配置信息
        Result<ListDictItemResponse> dictItem = dictClient.getDictItem(GetDictByCodeRequest.builder()
                .dictGroupCode(RepositoryConstant.REPOSITORY_SETTING)
                .dictCode(repositoryBO.getBelongType() == RepositoryConstant.BELONG_TYPE_TEAM ?
                        RepositoryConstant.REPOSITORY_UPPER_SIZE_TEAM :
                        RepositoryConstant.REPOSITORY_UPPER_SIZE_PERSON).build());
        //判断是否存在
        if (dictItem.wasSuccess()) {
            int row = repositoryManager.countRepository(RepositoryQuery.builder()
                    .belongType(repositoryBO.getBelongType())
                    .belongTo(repositoryBO.getBelongType() == RepositoryConstant.BELONG_TYPE_TEAM ? repositoryBO.getBelongTo() : UserContextHolder.getUserId()).build());
            if (row == Integer.parseInt(dictItem.getData().getDictValue())) {
                return Result.fail(Result.CONFLICT, "知识库数量已达上限");
            }
        }
        //新增
        RepositoryQuery query = RepositoryQuery.builder()
                .belongTo(repositoryBO.getBelongType() == RepositoryConstant.BELONG_TYPE_TEAM ? repositoryBO.getBelongTo() : UserContextHolder.getUserId())
                .repositoryName(repositoryBO.getRepositoryName()).build();
        //当判断名称重复
        List<RepositoryBO> repositoryPOS = repositoryManager.listRepositoryByName(query);
        if (!CollectionUtils.isEmpty(repositoryPOS)) {
            return Result.ofBadRequest("知识库名称重复");
        }
        int rows = saveRepositoryBO(repositoryBO);
        if (rows > 0) {
            return Result.success((long) rows);
        }
        return Result.ofErrorRowsAffected();
    }

    private int saveRepositoryBO(RepositoryBO repositoryBO) {
        //知识库数据完善
        buildRepositoryBO(repositoryBO);
        return repositoryManager.saveRepository(repositoryBO);
    }

    private void buildRepositoryBO(RepositoryBO repositoryBO) {
        if (repositoryBO.getBelongType() == 0) {
            repositoryBO.setBelongTo(UserContextHolder.getUserId());
        }
//		repositoryBO.setMemo("");//
        repositoryBO.setType(Objects.isNull(repositoryBO.getType()) ? 2 : repositoryBO.getType());
        repositoryBO.setCapacitySize(0L);//容量大小，单位字节，0表示无上限
        repositoryBO.setRepositorySize(0L);//知识库大小，单位字节
        repositoryBO.setTenantId(UserContextHolder.getTenantId());//租户Id，0表示不指定
        repositoryBO.setCreateUserId(UserContextHolder.getUserId());//创建用户id
        LocalDateTime now = LocalDateTime.now();
        repositoryBO.setCreateTime(now);//创建时间
        repositoryBO.setAccessTime(now);//最后访问事件
        repositoryBO.setUpdateTime(now);//修改事件
        repositoryBO.setDeleteFlag(Boolean.FALSE);//是否删除
    }

    @Transactional
    @Override
    public Result<?> updateRepository(RepositoryBO repositoryBO) {
        //判断新名称是否存在 当知识库类型为个人或者回收站的时候放入个人id,否则放入团队或者组织id
        RepositoryQuery query = RepositoryQuery.builder()
                .belongTo((repositoryBO.getBelongType() == RepositoryConstant.BELONG_TYPE_PRIVATE ||
                        repositoryBO.getBelongType() == RepositoryConstant.BELONG_TYPE_RUBBISH) ?
                        UserContextHolder.getUserId() : repositoryBO.getBelongTo())
                .repositoryName(repositoryBO.getRepositoryName()).build();
        List<RepositoryBO> repositoryBOS = repositoryManager.listRepositoryByName(query);
        Boolean flag = true;
        //判断如果不为空
        if (!CollectionUtils.isEmpty(repositoryBOS)) {
            //如果有数据代表有名称重复
            flag = false;
            //查出同名知识库，判断id是否相同
            if (repositoryBOS.get(0).getRepositoryId().equals(repositoryBO.getRepositoryId())) {
                flag = true;
            }
        }
        //不存在同名知识库执行修改操作
        if (flag) {
            LocalDateTime now = LocalDateTime.now();
            repositoryBO.setUpdateTime(now);
            repositoryBO.setAccessTime(now);
            int affectedRows = repositoryManager.updateRepository(repositoryBO);
            if (affectedRows > 0) {
                //修改文件夹与文档权限
                FolderBO folderBO = FolderBO.builder()
                        .permission(repositoryBO.getPermission())
                        .repositoryId(repositoryBO.getRepositoryId())
                        .build();
                int row = folderManager.updateFolderPermission(folderBO);

                DocumentBO documentBO = DocumentBO.builder()
                        .permission(repositoryBO.getPermission())
                        .repositoryId(repositoryBO.getRepositoryId())
                        .build();
                row = documentManager.updateDocumentPermission(documentBO);
                return Result.success();
            }
        }
        return Result.ofErrorRowsAffected();
    }

    /**
     * 未完成
     * @param repositoryId
     * @return
     */
    @Override
    public Result<?> deleteRepository(Long repositoryId) {
        //可加入判断当前身份，目前删除知识库需要提供
        Long userId = UserContextHolder.getUserId();
        RepositoryBO repositoryBO = RepositoryBO.builder().repositoryId(repositoryId).build();
        int affectedRows = repositoryManager.deleteRepository(repositoryBO);
        if (affectedRows > 0) {
            return Result.success();
        }
        return Result.ofErrorRowsAffected();
    }

    /**
     * @param repositoryIds
     * @return
     */
    @Override
    public Result<?> deleteRepositories(Collection<Long> repositoryIds) {
        int affectedRows = repositoryManager.deleteRepositoryByIds(repositoryIds);
        if (affectedRows > 0) {
            return Result.success(affectedRows);
        }
        return Result.ofErrorRowsAffected();
    }

    @Override
    public RepositoryBO getRepository(Long repositoryId) {
        return repositoryManager.getRepository(repositoryId);
    }

    @Override
    public List<RepositoryBO> listRepositoryById(Collection<Long> collection) {
        return repositoryManager.listRepositoryById(collection);
    }

    @Override
    public List<RepositoryBO> listRepository(RepositoryQuery query) {
        if (query.getBelongType() == 0) {
            query.setBelongTo(UserContextHolder.getUserId());
        }
        List<RepositoryBO> repositoryBOS = repositoryManager.listRepository(query);
        if (CollectionUtils.isEmpty(repositoryBOS)) {
            return Collections.emptyList();
        }
        Set<Long> teamIds = repositoryBOS.stream().filter(r -> r.getBelongType() == 1).map(RepositoryBO::getBelongTo).collect(Collectors.toSet());
        //是团队管理员的团队ID
        Set<Long> adminTeamIds = ResultUtils.get(teamClient.isTeamAdminS(GetTeamSRequest.builder().teamIds(teamIds).build()));
        Set<Long> collect = repositoryBOS.stream().map(RepositoryBO::getBelongTo).collect(Collectors.toSet());
        List<RepositoryBO> repositoryBOList = new ArrayList<>();
        if (query.getBelongType() == 1) {
            Result<List<GetTeamResponse>> listResult = teamClient.listTeamById(collect);
            if (!listResult.wasSuccess()) {
                return Collections.emptyList();
            }
            Result<UserDTO> user = userClient.getUser(GetUserRequest.builder()
                    .userId(UserContextHolder.getUserId())
                    .withRole(true).build());
            List<LongIdCodeName> rolelist = new ArrayList<>();
            if (user.getData() != null && user.getData().getRoleList() != null) {
                rolelist = user.getData().getRoleList();
            }
            Map<Long, GetTeamResponse> collect1 = listResult.getData().stream().collect(Collectors.toMap(e -> e.getTeamId(), e -> e));
            Set<String> finalRoleList = rolelist.stream().map(LongIdCodeName::getCode).collect(Collectors.toSet());
            if (!CollectionUtils.isEmpty(collect1)) {
                //若为系统管理员则满权限
                if (finalRoleList.contains("admin")) {
                    repositoryBOS.forEach(resp -> {
                        GetTeamResponse getTeamResponse = collect1.get(resp.getBelongTo());
                        if (Objects.nonNull(getTeamResponse)) {
                            resp.setBelongToName(getTeamResponse.getTeamName());
                        }
                        resp.setPermission(getAllPermissions());
                    });
                } else {
                    //若为团队管理员，则该团队下的库满权限
                    if (!CollectionUtils.isEmpty(adminTeamIds)) {
                        //取交集赋权限
                        repositoryBOList.addAll(repositoryBOS.stream().filter(item -> adminTeamIds.contains(item.getBelongTo())).collect(toList()));
                        repositoryBOList = repositoryBOList.stream()
                                .peek(resp -> {
                                    GetTeamResponse getTeamResponse = collect1.get(resp.getBelongTo());
                                    resp.setBelongToName(getTeamResponse.getTeamName());
                                    resp.setPermission(getAllPermissions());
                                })
                                .collect(Collectors.toList());
                        //取差集
                        repositoryBOS = repositoryBOS.stream().filter(item -> !adminTeamIds.contains(item.getBelongTo())).collect(toList());
                    }
                    repositoryBOS = repositoryBOS.stream()
                            .filter(resp -> DocumentPermissions.hasVisible(resp.getPermission()))
                            .peek(resp -> {
                                GetTeamResponse getTeamResponse = collect1.get(resp.getBelongTo());
                                resp.setBelongToName(getTeamResponse.getTeamName());
                            })
                            .collect(Collectors.toList());
                }
            }

        }
        if (query.getBelongType() == 0) {

//			userClient.buildByUser(folderBOS,
//					folderBOS.stream().map(e -> e.getCreateUserId()).collect(Collectors.toSet()),
//					FolderBO::getCreateUserId,
//					(folderBO, userDTO) -> folderBO.setCreatedName(userDTO.getUserName()));
            userClient.buildByUser(repositoryBOS,
                    repositoryBOS.stream().map(e -> e.getBelongTo()).collect(Collectors.toSet()),
                    RepositoryBO::getBelongTo,
                    (repositoryBO, userDTO) -> repositoryBO.setBelongToName(userDTO.getUserName()));
            if (!CollectionUtils.isEmpty(repositoryBOS)) {
                repositoryBOS = repositoryBOS.stream().peek(repo -> repo.setPermission(getAllPermissions())).collect(Collectors.toList());
            }
        }
        repositoryBOS.addAll(repositoryBOList);
        repositoryBOS = repositoryBOS.stream()
                .peek(resp -> {
                    resp.setSize(ConvertSizeUtils.readableFileSize(resp.getRepositorySize()));
                    resp.setAccessTimeString(CalendarUtils.getDeadlineString(resp.getAccessTime(), LocalDateTime.now()));
                })
                .collect(Collectors.toList());
        return repositoryBOS;
    }

    @Override
    public int countRepository(RepositoryQuery query) {
        return repositoryManager.countRepository(query);
    }

    @Override
    public Result<List<Object>> getRubbish() {
        RepositoryBO repositoryBO = documentEventBus.getRubbishRepository();
        Long repositoryId = repositoryBO.getRepositoryId();
        List<Object> documents = getDocuments(repositoryId);
        return Result.success(documents);
    }

    /**
     * 获取台账知识库内容
     * @return
     */
    @Override
    public Result<List<Object>> getLedger() {
        List<RepositoryBO> repositoryBOS = listRepository(RepositoryQuery.max().belongType(4).belongTo(UserContextHolder.getUserId()).build());
        Long repositoryId = null;
        if (CollectionUtils.isEmpty(repositoryBOS)) {
            repositoryId = saveRepositoryService(RepositoryBO.builder().belongType(4).belongTo(UserContextHolder.getUserId()).repositoryName("台账文件知识库").memo("台账知识库").permission(DocumentPermissions.getAllPermissions()).build()).getData();
        } else {
            repositoryId = repositoryBOS.get(0).getRepositoryId();
        }
        List<Object> documents = getDocuments(repositoryId);
        return Result.success(documents);
    }

    private List<Object> getDocuments(Long repositoryId) {
        if (repositoryId == null) {
            return null;
        }
        List<Object> objects = new ArrayList<>();
        List<FolderBO> folderBOS = folderManager.listFolder(FolderQuery.builder().repositoryId(repositoryId).build());
        List<GetFolderResponse> folderResponses = null;
        if (!CollectionUtils.isEmpty(folderBOS)) {
            userClient.buildByUser(folderBOS,
                    folderBOS.stream().map(e -> e.getCreateUserId()).collect(Collectors.toSet()),
                    FolderBO::getCreateUserId,
                    (folderBO, userDTO) -> folderBO.setCreatedName(userDTO.getUserName()));
            folderResponses = FolderConverter.toResponse(folderBOS);
            folderResponses = folderResponses.stream().peek(resp -> {
                        resp.setSize(ConvertSizeUtils.readableFileSize(resp.getFolderSize()));
                        resp.setAccessTimeString(CalendarUtils.getDeadlineString(resp.getUpdateTime(), LocalDateTime.now()));
                    })
                    .sorted((e1, e2) -> e2.getUpdateTime().compareTo(e1.getUpdateTime()))
                    .collect(Collectors.toList());
        }
        List<DocumentBO> documentBOS = documentManager.listDocument(DocumentQuery.builder().repositoryId(repositoryId).build());
        List<GetDocumentResponse> getDocumentResponses = null;
        if (!CollectionUtils.isEmpty(documentBOS)) {
            userClient.buildByUser(documentBOS,
                    documentBOS.stream().map(DocumentBO::getCreateUserId).collect(Collectors.toSet()),
                    DocumentBO::getCreateUserId,
                    (documentBO, userDTO) -> documentBO.setCreatedName(userDTO.getUserName()));
            getDocumentResponses = DocumentConverter.toResponse(documentBOS);
            getDocumentResponses = getDocumentResponses.stream().peek(resp -> {
                        resp.setSize(ConvertSizeUtils.readableFileSize(resp.getFileSize()));
                        resp.setAccessTimeString(CalendarUtils.getDeadlineString(resp.getUpdateTime(), LocalDateTime.now()));
                    })
                    .sorted((e1, e2) -> e2.getUpdateTime().compareTo(e1.getUpdateTime()))
                    .collect(Collectors.toList());
        }
        if (!CollectionUtils.isEmpty(folderResponses)) {
            objects.addAll(folderResponses);
        }
        if (!CollectionUtils.isEmpty(getDocumentResponses)) {
            objects.addAll(getDocumentResponses);
        }
        return objects;
    }

    @Override
    public Result<?> getUserGroupAndRepository() {
        Result<List<GetUserGroupResponse>> listResult = userGroupClient.listUserGroup(GetUserGroupByRequest.builder().type(0).build());
        if (!listResult.wasSuccess()) {
            return Result.ofErrorRowsAffected();
        }
        List<GetUserGroupResponse> data = listResult.getData();
        Set<Long> collect = data.stream().map(e -> e.getUserGroupId()).collect(Collectors.toSet());
        List<RepositoryBO> userGroupAndRepository = repositoryManager.getUserGroupAndRepository(collect);
        if (CollectionUtils.isEmpty(userGroupAndRepository)) {
            return Result.ofErrorRowsAffected();
        }
        List<GetRepositoryResponse> getRepositoryResponses = RepositoryConverter.toResponse(userGroupAndRepository);
        for (GetRepositoryResponse getRepositoryRespons : getRepositoryResponses) {
            for (int i = 0; i < data.size(); i++) {
                if (data.get(i).getUserGroupId() == getRepositoryRespons.getBelongTo()) {
                    List<Object> objects = data.get(i).getObjects();
                    if (CollectionUtils.isEmpty(objects)) {
                        objects = new ArrayList<>();
                    }
                    objects.add(getRepositoryRespons);
                    data.get(i).setObjects(objects);
                }
            }
        }
        return Result.success(data);
    }

    @Override
    public Result<GetRepositoryResponse> getReleaseRepositoryInfo() {
        RepositoryBO releaseRepository = repositoryManager.getReleaseRepository();
        if (Objects.isNull(releaseRepository)) {
            return Result.success();
        }
        return Result.success(RepositoryConverter.toResponse(releaseRepository));
    }

    /**
     * 根据用户及身份获取团队信息列表
     * @return
     */
    @Override
    public List<TeamRepositoryTreeItem> getUserTeamListTree(GetTypeRepositoryRequest request) {
        //构建查询
        RepositoryQuery repositoryQuery = RepositoryQuery.builder().belongTo(UserContextHolder.getUserId()).belongType(0).build();
        //个人知识库
        List<RepositoryBO> ownRepositoryBOS = repositoryManager.listRepository(repositoryQuery);
        ownRepositoryBOS = ownRepositoryBOS.stream().peek(repo -> repo.setPermission(getAllPermissions())).collect(Collectors.toList());
        List<RepositoryBO> repositoryBOS = new ArrayList<>();
        repositoryBOS.addAll(ownRepositoryBOS);
        List<TeamRepositoryTreeItem> tree = new ArrayList<>();
        //个人知识库不属于组织，单独添加
        if (Objects.nonNull(request.getPersonal()) && request.getPersonal()) {
            TeamRepositoryTreeItem treeItem = new TeamRepositoryTreeItem();
            //此处个人知识库仅用于显示，为避免与团队id混淆，使用-1为树的id
            treeItem.setId(RepositoryEnum.OWN_REPOSITORY.getCode());
            treeItem.setName(RepositoryEnum.OWN_REPOSITORY.getName());
            tree.add(treeItem);
        }
        if (!CollectionUtils.isEmpty(repositoryBOS)) {
            //将个人知识库的belongTO都赋为-1
            repositoryBOS.forEach(e -> e.setBelongTo(RepositoryEnum.OWN_REPOSITORY.getCode()));
        }
        Result<List<GetTeamResponse>> teamList = teamClient.listJoinedTeam(ListTeamRequest.builder().build());
        if (CollectionUtils.isEmpty(teamList.getData())) {
            Map<Long, List<RepositoryBO>> repoMap = repositoryBOS.stream().collect(Collectors.groupingBy(RepositoryBO::getBelongTo));
            addTree(tree, repoMap);
            return tree;
        }
        List<GetTeamResponse> getTeamResponses = teamList.getData();
        //筛选是管理员的团队id
        List<Long> managerTeamIds = getTeamResponses.stream().filter(resp -> resp.getRole() == 1).map(GetTeamResponse::getTeamId).collect(Collectors.toList());
        //筛选不是是管理员的团队id
        List<Long> userTeamIds = getTeamResponses.stream().filter(resp -> resp.getRole() == 0).map(GetTeamResponse::getTeamId).collect(Collectors.toList());
        //根据teamId查找库
        List<RepositoryBO> managerRepositoryBOS = new ArrayList<>();
        if (!CollectionUtils.isEmpty(managerTeamIds)) {
            RepositoryBO repositoryBO = RepositoryBO.builder().belongToIds(managerTeamIds).belongType(1).build();
            //管理员身份的库
            managerRepositoryBOS = repositoryManager.listRepositoryByBelongTo(repositoryBO);
            managerRepositoryBOS = managerRepositoryBOS.stream().peek(repo -> repo.setPermission(getAllPermissions())).collect(Collectors.toList());
        }
        List<RepositoryBO> userRepositoryBOS = new ArrayList<>();
        if (!CollectionUtils.isEmpty(userTeamIds)) {
            RepositoryBO repositoryBO1 = RepositoryBO.builder().belongToIds(userTeamIds).belongType(1).build();
            //非管理员身份的库
            userRepositoryBOS = repositoryManager.listRepositoryByBelongTo(repositoryBO1);
            userRepositoryBOS = getUserRepository(userRepositoryBOS, request.getPermission());
            //若为移动操作，携带源知识库参数
            if (null != request.getRepositoryId()) {
                boolean flag = false;
                for (RepositoryBO userRepositoryBO : userRepositoryBOS) {
                    if (userRepositoryBO.getRepositoryId().equals(request.getRepositoryId())) {
                        flag = true;
                    }
                }
                //若目的库无源库数据，则添加源库数据(只用于移动操作)
                if (!flag) {
                    RepositoryBO repository = repositoryManager.getRepository(request.getRepositoryId());
                    userRepositoryBOS.add(repository);
                }
            }
        }
        repositoryBOS.addAll(managerRepositoryBOS);
        repositoryBOS.addAll(userRepositoryBOS);
        Map<Long, List<RepositoryBO>> repoMap = repositoryBOS.stream().collect(Collectors.groupingBy(RepositoryBO::getBelongTo));
        //添加分组
        getTeamResponses.forEach(t -> {
            TeamRepositoryTreeItem node = new TeamRepositoryTreeItem();
            node.setId(t.getTeamId());
            node.setName(t.getTeamName());
            tree.add(node);
        });
        addTree(tree, repoMap);
        return tree;
    }

    /**
     * @author Greekn Zhang
     * @date 2021/5/8 9:54
     * @param userRepositoryBOS
     * @param permission
     * @return java.util.List<com.xy.biz.fd.domain.bo.RepositoryBO>
     * @description 判断权限(策略模式)
     */
    private List<RepositoryBO> getUserRepository(List<RepositoryBO> userRepositoryBOS, Integer permission) {
        if (DocumentPermissions.hasVisible(permission)) {
            userRepositoryBOS = generatorMap.get(REPOSITORY_FILTER + DocumentPermissions.VISIBLE).filter(userRepositoryBOS);
        }
        if (DocumentPermissions.hasPreview(permission)) {
            userRepositoryBOS = generatorMap.get(REPOSITORY_FILTER + DocumentPermissions.PREVIEW).filter(userRepositoryBOS);
        }
        if (DocumentPermissions.hasPrint(permission)) {
            userRepositoryBOS = generatorMap.get(REPOSITORY_FILTER + DocumentPermissions.PRINT).filter(userRepositoryBOS);
        }
        if (DocumentPermissions.hasDownload(permission)) {
            userRepositoryBOS = generatorMap.get(REPOSITORY_FILTER + DocumentPermissions.DOWNLOAD).filter(userRepositoryBOS);
        }
        if (DocumentPermissions.hasRename(permission)) {
            userRepositoryBOS = generatorMap.get(REPOSITORY_FILTER + DocumentPermissions.RENAME).filter(userRepositoryBOS);
        }
        if (DocumentPermissions.hasFavorite(permission)) {
            userRepositoryBOS = generatorMap.get(REPOSITORY_FILTER + DocumentPermissions.FAVORITE).filter(userRepositoryBOS);
        }
        if (DocumentPermissions.hasMove(permission)) {
            userRepositoryBOS = generatorMap.get(REPOSITORY_FILTER + DocumentPermissions.MOVE).filter(userRepositoryBOS);
        }
        if (DocumentPermissions.hasCopy(permission)) {
            userRepositoryBOS = generatorMap.get(REPOSITORY_FILTER + DocumentPermissions.COPY).filter(userRepositoryBOS);
        }
        if (DocumentPermissions.hasEdit(permission)) {
            userRepositoryBOS = generatorMap.get(REPOSITORY_FILTER + DocumentPermissions.EDIT).filter(userRepositoryBOS);
        }
        if (DocumentPermissions.hasNew(permission)) {
            userRepositoryBOS = generatorMap.get(REPOSITORY_FILTER + DocumentPermissions.NEW).filter(userRepositoryBOS);
        }
        if (DocumentPermissions.hasShare(permission)) {
            userRepositoryBOS = generatorMap.get(REPOSITORY_FILTER + DocumentPermissions.SHARE).filter(userRepositoryBOS);
        }
        if (DocumentPermissions.hasAssociate(permission)) {
            userRepositoryBOS = generatorMap.get(REPOSITORY_FILTER + DocumentPermissions.ASSOCIATE).filter(userRepositoryBOS);
        }
        if (DocumentPermissions.hasDelete(permission)) {
            userRepositoryBOS = generatorMap.get(REPOSITORY_FILTER + DocumentPermissions.DELETE).filter(userRepositoryBOS);
        }
        return userRepositoryBOS;
    }

    private Integer getAllPermissions() {
        Integer permissions = DocumentPermissions.VISIBLE +
                DocumentPermissions.PREVIEW +
                DocumentPermissions.PRINT +
                DocumentPermissions.DOWNLOAD +
                DocumentPermissions.RENAME +
                DocumentPermissions.FAVORITE +
                DocumentPermissions.MOVE +
                DocumentPermissions.COPY +
                DocumentPermissions.EDIT +
                DocumentPermissions.NEW +
                DocumentPermissions.SHARE +
                DocumentPermissions.ASSOCIATE +
                DocumentPermissions.DELETE;
        return permissions;
    }

    /**
     * @author Greekn Zhang
     * @date 2021/5/8 13:53
     * @param tree
     * @param repositoryGroup
     * @return java.util.List<com.xy.biz.fd.domain.vo.TeamRepositoryTreeItem>
     * @description 将节点添加进树
     */
    private List<TeamRepositoryTreeItem> addTree(List<TeamRepositoryTreeItem> tree, Map<Long, List<RepositoryBO>> repositoryGroup) {
        tree.forEach(t -> {
            if (repositoryGroup.containsKey(t.getId())) {
                List<RepositoryBO> repository = repositoryGroup.get(t.getId());
                List<TeamRepositoryTreeItem> treeNode = new ArrayList<>();
                repository.forEach(repo -> {
                    if (repo.getBelongType() == 0 && t.getId().equals(RepositoryEnum.OWN_REPOSITORY.getCode()) && RepositoryEnum.OWN_REPOSITORY.getName().equals(t.getName())) {
                        TeamRepositoryTreeItem node = new TeamRepositoryTreeItem();
                        node.setId(repo.getRepositoryId());
                        node.setPermissions(repo.getPermission());
                        node.setName(repo.getRepositoryName());
                        treeNode.add(node);
                    }
                    if (repo.getBelongType() == 1 && repo.getBelongTo().equals(t.getId())) {
                        TeamRepositoryTreeItem node = new TeamRepositoryTreeItem();
                        node.setId(repo.getRepositoryId());
                        node.setPermissions(repo.getPermission());
                        node.setName(repo.getRepositoryName());
                        treeNode.add(node);
                    }
                });
                t.setChildren(treeNode);
            }
        });
        return null;
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        documentEventBus.setRubbishRepositoryInitHandler(() -> {
            RepositoryQuery query = RepositoryQuery.one().belongType(RepositoryConstant.BELONG_TYPE_RUBBISH).belongTo(UserContextHolder.getUserId()).build();
            List<RepositoryBO> repositoryBOS = repositoryManager.listRubbishRepository(query);
            //判断回收站是否存在
            if (CollectionUtils.isEmpty(repositoryBOS)) {
                //新建回收站
                RepositoryBO repositoryBO = new RepositoryBO();
                repositoryBO.setBelongType(RepositoryConstant.BELONG_TYPE_RUBBISH);
                repositoryBO.setBelongTo(UserContextHolder.getUserId());
                repositoryBO.setMemo("初始化回收站");
                repositoryBO.setRepositoryName("回收站");
                boolean flag = false;
                for (int i = 0; i < 3; i++) {
                    if (saveRepository(repositoryBO).wasSuccess()) {
                        flag = true;
                        break;
                    }
                }
                if (flag) {
                    return repositoryBO;
                }
                return null;
            }
            return repositoryBOS.get(0);
        });
        //团队删除后知识库相应删除
        teamEventBusClient.addDocumentEditHandler((teamId) -> {
            List<RepositoryBO> repositoryBOS = repositoryManager.listRepository(RepositoryQuery.max().belongType(1).belongTo(teamId).build());
            Set<Long> ids = repositoryBOS.stream().map(RepositoryBO::getRepositoryId).collect(Collectors.toSet());
            if (!CollectionUtils.isEmpty(ids)) {
                deleteRepositories(ids);
            }
        });
        repositoryEventBus.addRepositoryHandler((documentId) -> {
            List<RepositoryBO> repositoryBOS = listRepository(RepositoryQuery.max().belongType(4).belongTo(UserContextHolder.getUserId()).build());
            if (CollectionUtils.isEmpty(repositoryBOS)) {
                //若当前用户无个人知识库，则新建，用于保存台账的线上文件
                Long repositoryId = saveRepositoryService(RepositoryBO.builder().belongType(4).belongTo(UserContextHolder.getUserId()).repositoryName("台账文件知识库").memo("台账知识库").permission(DocumentPermissions.getAllPermissions()).build()).getData();
                documentService.updateMoveDocument(DocumentBO.builder().documentId(documentId).folderId(0L).repositoryId(repositoryId).build());
            } else {
                repositoryBOS.sort(Comparator.comparing(RepositoryBO::getCreateTime));
                RepositoryBO repositoryBO = repositoryBOS.get(0);
                documentService.updateMoveDocument(DocumentBO.builder().documentId(documentId).folderId(0L).repositoryId(repositoryBO.getRepositoryId()).build());
            }
        });

        repositoryEventBus.addRepositoryQRHandler((documentId) -> {
            List<RepositoryBO> repositoryBOS = listRepository(RepositoryQuery.max().belongType(5).belongTo(UserContextHolder.getUserId()).build());
            if (CollectionUtils.isEmpty(repositoryBOS)) {
                //若当前用户无个人知识库，则新建，用于保存二维码的线上文件
                Long repositoryId = saveRepositoryService(RepositoryBO.builder().belongType(4).belongTo(UserContextHolder.getUserId()).repositoryName("二维码打印文件知识库").memo("二维码文件知识库").permission(DocumentPermissions.getAllPermissions()).build()).getData();
                documentService.updateMoveDocument(DocumentBO.builder().documentId(documentId).folderId(0L).repositoryId(repositoryId).build());
            } else {
                repositoryBOS.sort(Comparator.comparing(RepositoryBO::getCreateTime));
                RepositoryBO repositoryBO = repositoryBOS.get(0);
                documentService.updateMoveDocument(DocumentBO.builder().documentId(documentId).folderId(0L).repositoryId(repositoryBO.getRepositoryId()).build());
            }
        });
    }

    /**
     * @author Greekn Zhang
     * @date 2021/4/29 14:05
     * @param folderId
     * @param sb
     * @return java.lang.StringBuffer
     * @description 递归获取文件夹名字
     */
    private StringBuffer getFolderName(Long folderId, StringBuffer sb) {
        if (!Objects.isNull(folderId) && folderId != 0) {
            FolderBO folder = folderManager.getFolder(folderId);
            getFolderName(folder.getParentFolderId(), sb);
            return sb.append(folder.getFolderName()).append("/");
        } else {
            return null;
        }
    }
}
